#include "apimanager.h"
#include "configmanager.h"
#include "protection.h"
#include <QJsonParseError>
#include <QDebug>
#include <QStandardPaths>
#include <QDir>

// 单例实例
ApiManager* ApiManager::s_instance = nullptr;

ApiManager::ApiManager(QObject *parent)
    : QObject(parent)
    , m_networkManager(new QNetworkAccessManager(this))
    , m_heartbeatTimer(new QTimer(this))
    , m_heartbeatActive(false)
{

    // 连接心跳定时器
    connect(m_heartbeatTimer, &QTimer::timeout, this, &ApiManager::onHeartbeatTimer);

    // 从配置中加载API基础URL
    m_apiBase = ConfigManager::getApiBase();

    // ApiManager需要基础API路径，而不是登录URL
    if (m_apiBase.contains("/auth/client/login")) {
        // 移除登录路径部分，只保留基础API路径
        m_apiBase = "https://ctdy123.com/api";
        // 注意：不要修改ConfigManager中的apiBase，因为LoginDialog需要完整的登录URL
    }


    // 加载认证Token
    m_authToken = ConfigManager::getAuthToken();

}

ApiManager::~ApiManager()
{
    stopHeartbeat();
}

ApiManager* ApiManager::instance()
{
    if (!s_instance) {
        s_instance = new ApiManager();
    }
    return s_instance;
}

void ApiManager::setAuthToken(const QString& token)
{
    m_authToken = token;
    ConfigManager::setAuthToken(token);
}

QString ApiManager::getAuthToken() const
{
    return m_authToken;
}

bool ApiManager::hasValidToken() const
{
    return !m_authToken.isEmpty();
}

void ApiManager::startHeartbeat()
{
    if (m_heartbeatActive) {
        return;
    }

    if (!hasValidToken()) {
        emit apiError("无法启动心跳", "未找到有效的认证Token");
        return;
    }

    m_heartbeatActive = true;
    m_heartbeatTimer->start(HEARTBEAT_INTERVAL);

    // 立即发送一次心跳
    onHeartbeatTimer();
}

void ApiManager::stopHeartbeat()
{
    if (!m_heartbeatActive) {
        return;
    }

    m_heartbeatActive = false;
    m_heartbeatTimer->stop();
}

bool ApiManager::isHeartbeatActive() const
{
    return m_heartbeatActive;
}

void ApiManager::notifyVersionInfo(const QString& latestVersion, const QString& downloadUrl, const QString& releaseNotes, const QString& md5Hash)
{
    emit versionInfoReceived(latestVersion, downloadUrl, releaseNotes, md5Hash);
}

void ApiManager::notifySubscriptionInfo(const QJsonObject& subscription)
{
    emit userSubscriptionFetched(subscription);
}

void ApiManager::fetchUserProfile()
{
    if (!hasValidToken()) {
        emit apiError("无法获取用户信息", "未找到有效的认证Token");
        return;
    }

    QNetworkReply* reply = sendAuthenticatedRequest("/user/profile", QJsonObject(), "GET");
    connect(reply, &QNetworkReply::finished, this, &ApiManager::onUserProfileFinished);
}

void ApiManager::fetchUserSubscription()
{
    if (!hasValidToken()) {
        emit apiError("无法获取订阅信息", "未找到有效的认证Token");
        return;
    }

    QNetworkReply* reply = sendAuthenticatedRequest("/user/subscription");
    connect(reply, &QNetworkReply::finished, this, &ApiManager::onUserSubscriptionFinished);
}

void ApiManager::fetchDeviceList()
{
    if (!hasValidToken()) {
        emit apiError("无法获取设备列表", "未找到有效的认证Token");
        return;
    }

    QNetworkReply* reply = sendAuthenticatedRequest("/user/devices");
    connect(reply, &QNetworkReply::finished, this, &ApiManager::onDeviceListFinished);
}

void ApiManager::kickDevice(const QString& sessionId)
{
    if (!hasValidToken()) {
        emit deviceKickError("未找到有效的认证Token");
        return;
    }

    if (sessionId.isEmpty()) {
        emit deviceKickError("设备会话ID不能为空");
        return;
    }

    QJsonObject payload;
    payload["sessionId"] = sessionId;

    QNetworkReply* reply = sendAuthenticatedRequest("/sessions/kick", payload);
    connect(reply, &QNetworkReply::finished, this, &ApiManager::onDeviceKickFinished);
}

void ApiManager::logout()
{
    if (!hasValidToken()) {
        emit apiError("无法退出登录", "未找到有效的认证Token");
        return;
    }

    stopHeartbeat();

    QJsonObject payload;
    payload["sessionId"] = getSessionId();

    QNetworkReply* reply = sendAuthenticatedRequest("/auth/client/logout", payload);
    connect(reply, &QNetworkReply::finished, this, &ApiManager::onLogoutFinished);
}

void ApiManager::setApiBase(const QString& apiBase)
{
    m_apiBase = apiBase;
    ConfigManager::setApiBase(apiBase);
}

QString ApiManager::getApiBase() const
{
    return m_apiBase;
}

void ApiManager::sendHeartbeatForValidation()
{
    // 手动触发心跳验证（不依赖定时器状态）
    if (!hasValidToken()) {
        return;
    }

    QJsonObject payload;
    buildHeartbeatPayload(payload);

    QNetworkReply* reply = sendAuthenticatedRequest("/auth/client/heartbeat", payload);
    connect(reply, &QNetworkReply::finished, this, &ApiManager::onHeartbeatFinished);
}

void ApiManager::onHeartbeatTimer()
{
    if (!m_heartbeatActive || !hasValidToken()) {
        return;
    }

    QJsonObject payload;
    buildHeartbeatPayload(payload);

    QNetworkReply* reply = sendAuthenticatedRequest("/auth/client/heartbeat", payload);
    connect(reply, &QNetworkReply::finished, this, &ApiManager::onHeartbeatFinished);
}

void ApiManager::onHeartbeatFinished()
{
    QNetworkReply* reply = qobject_cast<QNetworkReply*>(sender());
    if (!reply) return;

    reply->deleteLater();

    if (reply->error() != QNetworkReply::NoError) {
        int statusCode = reply->attribute(QNetworkRequest::HttpStatusCodeAttribute).toInt();

        // 特殊处理心跳相关的HTTP状态码
        if (statusCode == 401 || statusCode == 403) {
            // 401/403可能表示设备被踢掉或Token过期，尝试解析响应
            QByteArray data = reply->readAll();
            QJsonDocument doc = QJsonDocument::fromJson(data);
            QJsonObject obj = doc.object();

            if (!obj.isEmpty() && isTokenExpired(obj)) {
                handleApiError(reply, "心跳保活");
                return;
            }
        }

        // 处理404响应 - 设备未找到(DEVICE_NOT_FOUND)
        if (statusCode == 404) {
            QByteArray data = reply->readAll();

            // 404表示设备记录不存在，需要清除本地Token并强制重新登录

            // 清除Token相关认证信息，但保留用户邮箱和密码
            m_authToken.clear();
            ConfigManager::setAuthToken("");
            ConfigManager::clearSubscriptionInfo();
            // 注意：保留邮箱和密码，方便用户重新登录

            // 发射设备失效信号，通知主窗口强制重新登录
            emit deviceNotFound();

            return;
        }

        handleNetworkError(reply, "心跳保活");
        return;
    }

    QByteArray data = reply->readAll();
    QJsonDocument doc = QJsonDocument::fromJson(data);
    QJsonObject obj = doc.object();

    if (!validateResponse(obj)) {
        handleApiError(reply, "心跳保活");
        return;
    }

    if (obj.contains("success") && obj["success"].toBool()) {
        QString message = obj.contains("message") ? obj["message"].toString() : "心跳成功";
        QString timestamp = obj.value("timestamp").toString();

        // 检查响应中是否包含更新信息（符合pc-client-auth-spec.md规范）
        if (obj.contains("updateInfo") && obj["updateInfo"].isObject()) {
            QJsonObject updateInfo = obj["updateInfo"].toObject();
            bool hasUpdate = updateInfo.value("hasUpdate").toBool();
            bool forceUpdate = updateInfo.value("forceUpdate").toBool();
            QString currentVersion = updateInfo.value("currentVersion").toString();
            QString latestVersion = updateInfo.value("latestVersion").toString();
            QString updateUrl = updateInfo.value("updateUrl").toString();
            QString updateLog = updateInfo.value("updateLog").toString();
            QString checksumMD5 = updateInfo.value("checksumMD5").toString();


            if (hasUpdate && !latestVersion.isEmpty()) {
                // 使用新的信号字段名，但保持接口兼容性
                emit versionInfoReceived(latestVersion, updateUrl, updateLog, checksumMD5);
            }
        }

        emit heartbeatSuccess();
    } else {
        emit heartbeatError("心跳请求失败");
    }
}

void ApiManager::onUserProfileFinished()
{
    QNetworkReply* reply = qobject_cast<QNetworkReply*>(sender());
    if (!reply) return;

    reply->deleteLater();

    if (reply->error() != QNetworkReply::NoError) {
        handleNetworkError(reply, "获取用户信息");
        return;
    }

    QByteArray data = reply->readAll();
    QJsonDocument doc = QJsonDocument::fromJson(data);
    QJsonObject obj = doc.object();

    if (!validateResponse(obj)) {
        handleApiError(reply, "获取用户信息");
        return;
    }

    if (obj.contains("success") && obj["success"].toBool() && obj.contains("user")) {
        QJsonObject userProfile = obj["user"].toObject();
        if (validateUserProfile(userProfile)) {
            emit userProfileFetched(userProfile);
        } else {
            emit apiError("用户信息格式错误", "服务器返回的用户信息格式不正确");
        }
    } else {
        handleApiError(reply, "获取用户信息");
    }
}

void ApiManager::onUserSubscriptionFinished()
{
    QNetworkReply* reply = qobject_cast<QNetworkReply*>(sender());
    if (!reply) return;

    reply->deleteLater();

    if (reply->error() != QNetworkReply::NoError) {
        handleNetworkError(reply, "获取订阅信息");
        return;
    }

    QByteArray data = reply->readAll();
    QJsonDocument doc = QJsonDocument::fromJson(data);
    QJsonObject obj = doc.object();

    if (!validateResponse(obj)) {
        handleApiError(reply, "获取订阅信息");
        return;
    }

    if (obj.contains("success") && obj["success"].toBool() && obj.contains("subscription")) {
        QJsonObject subscription = obj["subscription"].toObject();
        if (validateSubscription(subscription)) {
            emit userSubscriptionFetched(subscription);
        } else {
            emit apiError("订阅信息格式错误", "服务器返回的订阅信息格式不正确");
        }
    } else {
        handleApiError(reply, "获取订阅信息");
    }
}

void ApiManager::onDeviceListFinished()
{
    QNetworkReply* reply = qobject_cast<QNetworkReply*>(sender());
    if (!reply) return;

    reply->deleteLater();

    if (reply->error() != QNetworkReply::NoError) {
        handleNetworkError(reply, "获取设备列表");
        return;
    }

    QByteArray data = reply->readAll();
    QJsonDocument doc = QJsonDocument::fromJson(data);
    QJsonObject obj = doc.object();

    if (!validateResponse(obj)) {
        handleApiError(reply, "获取设备列表");
        return;
    }

    if (obj.contains("success") && obj["success"].toBool()) {
        if (obj.contains("devices")) {
            QJsonValue devicesValue = obj["devices"];
            QJsonArray devices;

            if (devicesValue.isArray()) {
                devices = devicesValue.toArray();
            } else if (devicesValue.isObject()) {
                QJsonObject devicesObj = devicesValue.toObject();
                if (devicesObj.contains("active") && devicesObj["active"].isArray()) {
                    devices = devicesObj["active"].toArray();
                }
            }

            emit deviceListFetched(devices);
        } else {
            emit apiError("设备列表格式错误", "服务器返回的设备列表格式不正确");
        }
    } else {
        handleApiError(reply, "获取设备列表");
    }
}

void ApiManager::onDeviceKickFinished()
{
    QNetworkReply* reply = qobject_cast<QNetworkReply*>(sender());
    if (!reply) return;

    reply->deleteLater();

    QString sessionId = reply->property("sessionId").toString();

    if (reply->error() != QNetworkReply::NoError) {
        emit deviceKickError(reply->errorString());
        return;
    }

    QByteArray data = reply->readAll();
    QJsonDocument doc = QJsonDocument::fromJson(data);
    QJsonObject obj = doc.object();

    if (!validateResponse(obj)) {
        handleApiError(reply, "踢掉设备");
        return;
    }

    if (obj.contains("success") && obj["success"].toBool()) {
        emit deviceKickSuccess(sessionId);
    } else {
        QString message = obj.contains("message") ? obj["message"].toString() : "踢掉设备失败";
        emit deviceKickError(message);
    }
}

void ApiManager::onLogoutFinished()
{
    QNetworkReply* reply = qobject_cast<QNetworkReply*>(sender());
    if (!reply) return;

    reply->deleteLater();

    if (reply->error() != QNetworkReply::NoError) {
        emit apiError("退出登录失败", reply->errorString());
        return;
    }

    QByteArray data = reply->readAll();
    QJsonDocument doc = QJsonDocument::fromJson(data);
    QJsonObject obj = doc.object();


    // 无论服务器响应如何，都清除本地Token
    m_authToken.clear();
    ConfigManager::setAuthToken("");

    bool success = obj.contains("success") && obj["success"].toBool();
    if (success) {
    } else {
    }

    // 发出注销完成信号
    emit logoutFinished(success);

    // 停止心跳
    stopHeartbeat();
}

QNetworkReply* ApiManager::sendApiRequest(const QString& endpoint,
                                          const QJsonObject& data,
                                          const QString& method)
{
    QUrl url = buildApiUrl(endpoint);
    QNetworkRequest request(url);

    request.setHeader(QNetworkRequest::ContentTypeHeader, "application/json");
    request.setRawHeader("Accept", "application/json");
    request.setRawHeader("User-Agent", LimeReader::AppVersion::getUserAgent().toUtf8());

    QJsonDocument doc(data);
    QByteArray jsonData = doc.toJson();


    QNetworkReply* reply = nullptr;

    if (method.toUpper() == "GET") {
        reply = m_networkManager->get(request);
    } else if (method.toUpper() == "POST") {
        reply = m_networkManager->post(request, jsonData);
    } else if (method.toUpper() == "PUT") {
        reply = m_networkManager->put(request, jsonData);
    } else if (method.toUpper() == "DELETE") {
        reply = m_networkManager->deleteResource(request);
    }

    return reply;
}

QNetworkReply* ApiManager::sendAuthenticatedRequest(const QString& endpoint,
                                                    const QJsonObject& data,
                                                    const QString& method)
{
    if (!hasValidToken()) {
        return nullptr;
    }

    QUrl url = buildApiUrl(endpoint);
    QNetworkRequest request(url);

    request.setHeader(QNetworkRequest::ContentTypeHeader, "application/json");
    request.setRawHeader("Accept", "application/json");
    request.setRawHeader("Authorization", QString("Bearer %1").arg(m_authToken).toUtf8());
    request.setRawHeader("User-Agent", LimeReader::AppVersion::getUserAgent().toUtf8());

    QJsonDocument doc(data);
    QByteArray jsonData = doc.toJson();


    QNetworkReply* reply = nullptr;

    if (method.toUpper() == "GET") {
        reply = m_networkManager->get(request);
    } else if (method.toUpper() == "POST") {
        reply = m_networkManager->post(request, jsonData);
    } else if (method.toUpper() == "PUT") {
        reply = m_networkManager->put(request, jsonData);
    } else if (method.toUpper() == "DELETE") {
        reply = m_networkManager->deleteResource(request);
    }

    return reply;
}

void ApiManager::handleNetworkError(QNetworkReply* reply, const QString& context)
{
    QString errorString = reply->errorString();
    int statusCode = reply->attribute(QNetworkRequest::HttpStatusCodeAttribute).toInt();


    emit networkError(QString("%1 (HTTP %2)").arg(errorString).arg(statusCode));
}

void ApiManager::handleApiError(QNetworkReply* reply, const QString& context)
{
    QByteArray data = reply->readAll();
    QJsonDocument doc = QJsonDocument::fromJson(data);
    QJsonObject obj = doc.object();

    int statusCode = reply->attribute(QNetworkRequest::HttpStatusCodeAttribute).toInt();
    QString errorString = reply->errorString();


    // 检查是否Token过期
    if (isTokenExpired(obj)) {
        m_authToken.clear();
        ConfigManager::setAuthToken("");
        emit tokenExpired();
        return;
    }

    QString message = obj.contains("message") ? obj["message"].toString() : QString("%1失败").arg(context);
    emit apiError(message, errorString);
}

bool ApiManager::isTokenExpired(const QJsonObject& errorResponse)
{
    return errorResponse.value("error").toString() == "TOKEN_EXPIRED" ||
           errorResponse.value("code").toString() == "401";
}

void ApiManager::buildHeartbeatPayload(QJsonObject& payload) const
{
    // 根据pc-client-auth-spec.md规范构建心跳载荷
    payload["currentVersion"] = LimeReader::AppVersion::getAppVersion();
    payload["clientName"] = "LimeReader";

    // 添加平台信息
#if defined(Q_OS_WIN)
    payload["platform"] = "windows";
#elif defined(Q_OS_MACOS)
    payload["platform"] = "macos";
#elif defined(Q_OS_LINUX)
    payload["platform"] = "linux";
#else
    payload["platform"] = "unknown";
#endif
}

QUrl ApiManager::buildApiUrl(const QString& endpoint) const
{
    if (m_apiBase.isEmpty()) {
        return QUrl(endpoint);
    }

    QString fullUrl = m_apiBase;
    if (!fullUrl.endsWith("/") && !endpoint.startsWith("/")) {
        fullUrl += "/";
    }
    fullUrl += endpoint;

    return QUrl(fullUrl);
}

QString ApiManager::getSessionId() const
{
    // 使用设备机器码作为会话ID
    return Protection::machineIDHashKey();
}

bool ApiManager::validateResponse(const QJsonObject& response) const
{
    return response.contains("success");
}

bool ApiManager::validateUserProfile(const QJsonObject& profile) const
{
    return profile.contains("id") && profile.contains("email");
}

bool ApiManager::validateSubscription(const QJsonObject& subscription) const
{
    return subscription.contains("type") && subscription.contains("active");
}